home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / spawn.c < prev    next >
C/C++ Source or Header  |  1992-03-29  |  4KB  |  162 lines

  1. /*
  2.    89/03/02: ERS: added the "mode" argument for MS-DOS/Unix
  3.    compatibility. Added prototypes for GNU C.
  4.  
  5.    fixed spawnve: the original didn't pass the command tail
  6.    correctly, nor did it handle errno right. Also, this version
  7.    passes args in the environment as well as the command line,
  8.    using the ARGV= mechanism supported by crt0.s
  9.  
  10.    Written 89/01/10 by ERS. Original version Copyright (c) 1988 by
  11.    Memorial University of Newfoundland. This version is based upon
  12.    that original, but is substantially different. (In fact, there
  13.    probably isn't a single line of the original left.)
  14.  
  15.    Adapted 90/06/25 by ERS to MiNT.
  16. */
  17.  
  18. #include    <stdarg.h>
  19. #include    <process.h>
  20. #include    <param.h>
  21. #include    <errno.h>
  22. #include    <osbind.h>
  23. #include    <mintbind.h>
  24. #include    <stdlib.h>
  25. #include    <time.h>
  26. #include    <string.h>
  27. #include    "lib.h"
  28.  
  29. #define TOS_ARGS 126
  30.  
  31. extern char **environ;
  32. extern int __mint;
  33.  
  34. static    char    cmd[TOS_ARGS+1];
  35.  
  36. int
  37. _spawnve(mode, _path, argv, envp)
  38.     int    mode;
  39.     char    *_path;
  40.     char    **argv;
  41.     char    **envp;
  42. {
  43.     extern void _exit();
  44.     static char    path[MAXPATHLEN];
  45.     int        cmlen;
  46.     int        enlen = 0;
  47.     char        *p;
  48.     char        *s, *t;
  49.     char        *env;
  50.     long        rval;
  51.  
  52.     if (mode != P_WAIT && mode != P_OVERLAY && mode != P_NOWAIT) {
  53.         errno = EINVAL;
  54.         return -1;
  55.     }
  56.     (void)_unx2dos(_path, path);    /* convert filename, if necessary */
  57.     if (!envp)
  58.         envp = environ;
  59.  
  60. /* count up space needed for environment */
  61.     for(cmlen = 0; argv[cmlen]; cmlen++)
  62.         enlen += strlen(argv[cmlen]) + 1;
  63.     for(cmlen = 0; envp[cmlen]; cmlen++)
  64.         enlen += strlen(envp[cmlen]) + 1;
  65.     enlen += 32;    /* filler for stuff like ARGV= and zeros */
  66.  
  67.     if (!(env = (char *)Malloc((long)enlen))) {
  68.         errno = ENOMEM;
  69.         return -1;
  70.     }
  71.     s = env;
  72.     while ((p = *envp) != 0) {
  73. /*
  74.  * NOTE: in main.c, we converted the PATH environment variable into
  75.  * POSIX form. Here, we convert back into gulam form. Note that the
  76.  * new variable will be shorter than the old, so space is not a problem.
  77.  */
  78.         if (!strncmp(p, "PATH=", 5)) {
  79.             strncpy(s, p, 5); s += 5; p += 5;
  80.             while (*p) {
  81.                 if (!strncmp(p, "/dev/", 5) && p[5]) {
  82.                     *s++ = p[5];
  83.                     *s++ = ':';
  84.                     p += 6;
  85.                 } else if (*p == ':') {
  86.                     *s++ = ','; p++;
  87.                 } else if (*p == '/') {
  88.                     *s++ = '\\'; p++;
  89.                 } else {
  90.                     *s++ = *p++;
  91.                 }
  92.             }
  93.         } else {
  94.             while(*p)
  95.                 *s++ = *p++;
  96.         }
  97.         *s++ = '\0';
  98.         envp++;
  99.     }
  100.     
  101.     strcpy(s, "ARGV=");
  102.     s += 6; /* s+=sizeof("ARGV=") */
  103.  
  104. /* copy argv[0] first (because it doesn't go into the command line */
  105.     if (argv && *argv) {
  106.         for (p = *argv; *p; )
  107.             *s++ = *p++;
  108.         *s++ = '\0';
  109.     }
  110.  
  111.     bzero(t = cmd, sizeof(cmd));
  112.  
  113. /* s points at the environment's copy of the args */
  114. /* t points at the command line copy to be put in the basepage */
  115.  
  116.         cmlen = 0;
  117.     if (argv && *argv) {
  118.         t++;
  119.         while (*++argv) {
  120.             p = *argv;
  121.             while (*p) {
  122.                               if (cmlen <= TOS_ARGS) {
  123.                                       *t++ = *p; cmlen++;
  124.                               }
  125.                 *s++ = *p++;
  126.             }
  127.                         if (cmlen <= TOS_ARGS && *(argv+1)) {
  128.                                 *t++ = ' '; cmlen++;
  129.                         }
  130.             *s++ = '\0';
  131.         }
  132. /*                *cmd = (char) cmlen;  NOT ANY MORE */
  133.     }
  134.  
  135.     /* tie off environment */
  136.     *s++ = '\0';
  137.     *s = '\0';
  138.  
  139.     /* signal Extended Argument Passing */
  140.     *cmd = 0x7f;
  141.  
  142. /* MiNT and MicroRTX support background processes with Pexec(100,...) */
  143. /* MiNT supports overlays with Pexec(200,...) */
  144.  
  145.     if (mode == P_NOWAIT) cmlen = 100;
  146.     else if (mode == P_OVERLAY && __mint) cmlen = 200;
  147.     else cmlen = 0;
  148.  
  149.     rval = Pexec(cmlen, path, cmd, env);
  150.  
  151.     if (rval < 0)
  152.     {
  153.         errno = -rval;
  154.         rval = -1;
  155.     }
  156.     else if (mode == P_OVERLAY)
  157.     /* note that we get here only if MiNT is not active! */
  158.         _exit((int)rval);
  159.     (void)Mfree(env);
  160.     return rval;
  161. }
  162.